package edu.hznu.crypto.algsm2demo;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * SM2 密钥反序列化Demo
 *
 * {@link org.bouncycastle.jcajce.provider.test.GeneralKeyTest#testSM2}
 *
 * @author 权观宇
 * @since 2020-04-13 21:43:02
 */
public class SM2KeyPairInjectDemo {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        final BouncyCastleProvider bc = new BouncyCastleProvider();
//        // 公私钥是16进制情况下解码
//        byte[] encPub = Hex.decode("...");
//        byte[] encPriv =  Hex.decode("...");

        // 公私钥是 Base64编码情况下解码
        String publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEmGVlevdMFmGRwzoP4+MUQNVW5o0WQDlIA3S1M2i81Yc3sjYWye+SErVxuOhicTUdObEi+E8z6WY2JvotcH2TTA==";
        String privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgm74YA0EC0MTj7NPI6LNSIxKYn0sp7BocSWcmMr0Bu+igCgYIKoEcz1UBgi2hRANCAASYZWV690wWYZHDOg/j4xRA1VbmjRZAOUgDdLUzaLzVhzeyNhbJ75IStXG46GJxNR05sSL4TzPpZjYm+i1wfZNM";
        System.out.println("公钥: " + publicKey);
        System.out.println("私钥: " + privateKey);
        byte[] encPub = Base64.decode(publicKey);
        byte[] encPriv = Base64.decode(privateKey);


        KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
        // 根据采用的编码结构反序列化公私钥
        PublicKey pub = keyFact.generatePublic(new X509EncodedKeySpec(encPub));
        PrivateKey priv = keyFact.generatePrivate(new PKCS8EncodedKeySpec(encPriv));

        Signature signature = Signature.getInstance("SM3withSm2", bc);

        // 签名原文
        byte[] plainText = "你好".getBytes(StandardCharsets.UTF_8);
        /*
         * 签名
         */
        // 签名需要使用私钥，使用私钥 初始化签名实例
        signature.initSign(priv);
        // 写入签名原文到算法中
        signature.update(plainText);
        // 计算签名值
        byte[] signatureValue = signature.sign();
        System.out.println("签名值: " + Hex.toHexString(signatureValue));

        /*
         * 验签
         */
        // 签名需要使用公钥，使用公钥 初始化签名实例
        signature.initVerify(pub);
        // 写入待验签的签名原文到算法中
        signature.update(plainText);
        // 验证签名值
        boolean res = signature.verify(signatureValue);
        System.out.println(">> 验证结果:" + res);
    }
}
